package cn.lisens.valid.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.ConstraintViolation;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import cn.lisens.valid.entity.User;
import cn.lisens.valid.utils.ValidatorUtils;
import lombok.Data;

@RestController
@Validated
public class UserController {
	
	@Value("${testrand}")
	private Integer testint;

	/**
	 * 参数上直接校验，需要类上加@Validated，参数上加 @NotBlank 
	 * 触发全局ConstraintViolationException
	 * @param username
	 * @param age
	 * @return
	 */
	@GetMapping("/argumentValid")
    public ResponseEntity<?> getUsers(
            @RequestParam @NotBlank(message = "用户名不能为空") String username,
            @RequestParam @Min(value = 1, message = "年龄必须大于0") Integer age) {
        // 业务逻辑
        return ResponseEntity.ok("校验通过");
    }
	
	/**
	 * form提交或者query参数传递到dto对象中，需要添加@Valid
	 * 触发全局BindException异常
	 * @param user
	 * @return
	 */
	@GetMapping("/dtoValid")
	public User complexSearch(@Valid User user) {
	    // 业务逻辑
		System.err.println(user.getBirth());
	    return user;
	}
	
	/**
	 * json提交数据，需要添加@Valid 和 @RequestBody
	 * 触发全局MethodArgumentNotValidException
	 * @param user
	 * @return
	 */
	@GetMapping("/jsonValid")
	public User save(@Valid @RequestBody User user) {
	    // 业务逻辑
		System.err.println(user.getBirth());
	    return user;
	}
	
	/**
	 * 手工校验对象参数，更灵活
	 * @param user
	 * @return
	 */
	@GetMapping("/manualValid")
	public String validManual(User user) {
		ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
		Validator validator = vf.getValidator();
		Set<ConstraintViolation<User>> set = validator.validate(user);
		for (ConstraintViolation<User> constraintViolation : set) {
		    System.out.println(constraintViolation.getMessage());
		}
		String err = ValidatorUtils.validateGetError(user);
		System.err.println(err);
	    return "checkerr: " + err;
	}
	
	
	
	/**
	 * 接收基础类型的数组
	 * 前端query或form传递ids=1&ids=2 或者ids=1,2 用逗号隔开
	 * @param ids
	 * @return
	 */
	@GetMapping("/arrayInteger")
	public String arrayInteger(@RequestParam("ids") Integer[] ids) {
	    return "Received: " + Arrays.toString(ids);
	}
	
	/**
	 * json接收Integer类型的数组
	 * 前端body传递[1,2,3,4]
	 * @param ids
	 * @return
	 */
	@PostMapping("/jsonIntegerList")
	public String jsonIntegerList(@RequestBody List<Integer> ids) {
	    return "Received: " + ids;
	}
	
	/**
	 * 接收基础类型的数组，可以省略@RequestParam
	 * 前端传递ids=aaa&ids=bbb 或者ids=aaa,bbb 用逗号隔开
	 * @param ids
	 * @return
	 */
	@GetMapping("/arrayString")
	public String arrayString(String[] ids) {
	    return "Received: " + Arrays.toString(ids);
	}
	
	/**
	 * 接收基础类型的List，需要添加 @RequestParam
	 * 不加 @RequestParam 会报错：No primary or single unique constructor found for interface java.util.List
	 * 前端传递有2中模式 ids=aaa&ids=bbb 或者ids=aaa,bbb 用逗号隔开，注意两种模式共存的话，优先使用第一种模式
	 * @param ids
	 * @return
	 */
	@GetMapping("/listString")
	public String listString(@RequestParam List<String> ids) {
	    return "Received: "+ids.size()+ ids;
	}
	
	/**
	 * json接收Integer类型的数组
	 * 前端body传递["aaa","bbb"]
	 * @param ids
	 * @return
	 */
	@PostMapping("/jsonStringList")
	public String jsonStringList(@RequestBody List<String> ids) {
	    return "Received: " + ids;
	}
	
	/**
	 * 接收DTO对象，@ModelAttribute可加可不加
	 * @param user
	 * @return
	 */
	@GetMapping("/dto")
	public String dto(@ModelAttribute User user) {
	    return "Received: " + user;
	}
	
	/**
	 * 不知道如何接收参数
	 * @param users
	 * @return
	 */
	@GetMapping("/dtoList")
	public String dtoList(@RequestParam List<User> users) {
	    return "Received: " + users;
	}
	
	/**
	 * 接收DTO的属性是List对象,@ModelAttribute可省略
	 * 前端传递Post发起form请求，body的key格式：users[0].username，传递多个，下标增加即可
	 * @param request
	 * @return
	 */
	@PostMapping("/dtoSubList")
	public String dtoSubList(RequestUsers request) {
	    return "Received: " + request.getUsers();
	}
	
	/**
	 * json接收List的对象，需要加 @RequestBody
	 * 前端body传递[{"username":"aaa"},{"username":"bbb"}]
	 * @param users
	 * @return
	 */
	@PostMapping("/jsonDtoList")
	public String jsonDtoList(@RequestBody List<User> users) {
	    return "Received: " + users;
	}
	
	@RequestMapping("/date")
	public Date date(Date date) {
		System.err.println(date);
	    return date;
	}
	
	@RequestMapping("rand")
	public Integer rand() {
		return testint;
	}
	
	@Data
	public static class RequestUsers{
		private List<User> users = new ArrayList<>();
	}
}
